#pragma execution_character_set("utf-8")

#include "StringTool.h"
#include <codecvt>
#include <locale>
#include <random>

//将string转换成wstring
std::wstring StringTool::string2wstring(std::string str, int encode)
{
    std::wstring result;
    //获取缓冲区大小，并申请空间，缓冲区大小按字符计算
    int len = MultiByteToWideChar(encode, 0, str.c_str(), str.size(), NULL, 0);
    TCHAR *buffer = new TCHAR[len + 1];
    //多字节编码转换成宽字节编码
    MultiByteToWideChar(encode, 0, str.c_str(), str.size(), buffer, len);
    buffer[len] = '\0'; //添加字符串结尾
    //删除缓冲区并返回值
    result.append(buffer);
    delete[] buffer;
    return result;
}

//将wstring转换成string
std::string StringTool::wstring2string(std::wstring wstr, int encode)
{
    std::string result;
    //获取缓冲区大小，并申请空间，缓冲区大小事按字节计算的
    int len = WideCharToMultiByte(encode, 0, wstr.c_str(), wstr.size(), NULL, 0, NULL, NULL);
    char *buffer = new char[len + 1];
    //宽字节编码转换成多字节编码
    WideCharToMultiByte(encode, 0, wstr.c_str(), wstr.size(), buffer, len, NULL, NULL);
    buffer[len] = '\0';
    //删除缓冲区并返回值
    result.append(buffer);
    delete[] buffer;
    return result;
}

std::wstring StringTool::formatTime(uint64_t msTime)
{
    wchar_t str[64] = {0};
    if (msTime < 60 * 1000)
    {
        int iSec = msTime / 1000;
        swprintf_s(str, L"%d 秒", iSec);
    }
    else if (msTime < 3600 * 1000)
    {
        int iSec = msTime / 1000;
        int iMin = iSec / 60;
        iSec = iSec % 60;

        swprintf_s(str, L"%d 分钟 %d 秒", iMin, iSec);
    }
    else
    {
        int iSec = msTime / 1000;
        int iMin = iSec / 60;
        int iHour = iMin / 60;

        iMin = iSec % 60;
        iSec = iSec % 60;

        swprintf_s(str, L"%d 小时 %d 分钟 %d 秒", iHour, iMin, iSec);
    }

    return std::wstring(str);
}

std::vector<std::string> StringTool::Stringsplit(std::string str, const char split)
{
    std::vector<std::string> retVal;
    std::istringstream iss(str);       // 输入流
    std::string token;                 // 接收缓冲区
    while (getline(iss, token, split)) // 以split为分隔符
    {
        retVal.push_back(token);
    }

    return retVal;
}

std::vector<std::wstring> StringTool::WStringsplit(std::wstring str, const wchar_t split)
{
    std::vector<std::wstring> retVal;
    std::wstringstream iss(str);       // 输入流
    std::wstring token;                // 接收缓冲区
    while (getline(iss, token, split)) // 以split为分隔符
    {
        retVal.push_back(token);
    }

    return retVal;
}

std::string StringTool::GetStrTime_Now()
{
    time_t now = time(0);
    tm ltm;
    localtime_s(&ltm, &now);

    char strTime[30] = {0};

    sprintf_s(strTime, "%d-%02d-%02d %02d:%02d:%02d",
              ltm.tm_year + 1900,
              ltm.tm_mon + 1,
              ltm.tm_mday,
              ltm.tm_hour,
              ltm.tm_min,
              ltm.tm_sec);

    return std::string(strTime);
}

std::wstring StringTool::DetTimeStamp_to_wstring(uint64_t ts)
{
    ULARGE_INTEGER ulVal;
    FILETIME fileTime;
    SYSTEMTIME sysTime;
    wchar_t retVal[64] = {0};
    int us_count = (ts % 10000) / 10;
    int ns_count = ts % 10; //unit: 100ns

    ulVal.QuadPart = ts;
    fileTime.dwHighDateTime = ulVal.HighPart;
    fileTime.dwLowDateTime = ulVal.LowPart;

    FileTimeToSystemTime(&fileTime, &sysTime);

    swprintf_s(retVal, L"%d-%02d-%02d %02d:%02d:%02d:%03d:%03d:%d",
               sysTime.wYear, sysTime.wMonth, sysTime.wDay,
               sysTime.wHour, sysTime.wMinute, sysTime.wSecond,
               sysTime.wMilliseconds, us_count, ns_count);

    return std::wstring(retVal);
}

std::string StringTool::TimeStamp_to_String(uint64_t ts, int X_10_ns)
{
    ULARGE_INTEGER ulVal;
    FILETIME fileTime;
    SYSTEMTIME sysTime;
    char retVal[64] = {0};
    int us_count = (ts % 10000) / 10;
    int ns_count = ts % 10; //unit: 100ns

    ulVal.QuadPart = ts;
    fileTime.dwHighDateTime = ulVal.HighPart;
    fileTime.dwLowDateTime = ulVal.LowPart;

    FileTimeToSystemTime(&fileTime, &sysTime);

    //2024 10 23 04 44 14 536 000 31

    sprintf_s(retVal, "%d%02d%02d%02d%02d%02d%03d%03d%d%d",
              sysTime.wYear, sysTime.wMonth, sysTime.wDay,
              sysTime.wHour, sysTime.wMinute, sysTime.wSecond,
              sysTime.wMilliseconds, us_count, ns_count, X_10_ns);

    return std::string(retVal);
}

//格式化出来的字符串也是到10纳秒。和上个函数功能一模一样
std::string StringTool::FtTimeStamp_to_String(uint64_t &ft100ns, uint32_t &ft10ns)
{
    ULARGE_INTEGER ulVal;
    FILETIME fileTime;
    SYSTEMTIME sysTime;
    char retVal[64] = {0};

    ulVal.QuadPart = ft100ns;
    fileTime.dwHighDateTime = ulVal.HighPart;
    fileTime.dwLowDateTime = ulVal.LowPart;

    FileTimeToSystemTime(&fileTime, &sysTime);

    //2024 10 23 04 44 14 536 000 31

    sprintf_s(retVal, "%d%02d%02d%02d%02d%02d%08d",
              sysTime.wYear, sysTime.wMonth, sysTime.wDay,
              sysTime.wHour, sysTime.wMinute, sysTime.wSecond, ft10ns);

    return std::string(retVal);
}

//'2024-03-06 09:22:50.2880000'
std::string StringTool::uint64TS_to_SqlDateTime2(uint64_t ts)
{
    ULARGE_INTEGER ulVal;
    FILETIME fileTime;
    SYSTEMTIME sysTime;
    char retVal[64] = {0};
    int UsNs = ts % 10000;

    ulVal.QuadPart = ts;
    fileTime.dwHighDateTime = ulVal.HighPart;
    fileTime.dwLowDateTime = ulVal.LowPart;

    FileTimeToSystemTime(&fileTime, &sysTime);

    sprintf_s(retVal, "%d-%02d-%02d %02d:%02d:%02d.%03d%04d",
              sysTime.wYear, sysTime.wMonth, sysTime.wDay,
              sysTime.wHour, sysTime.wMinute, sysTime.wSecond,
              sysTime.wMilliseconds, UsNs);

    return std::string(retVal);
}

std::wstring StringTool::TimeStamp_to_WString(uint64_t ts, int X_10_ns)
{
    ULARGE_INTEGER ulVal;
    FILETIME fileTime;
    SYSTEMTIME sysTime;
    wchar_t retVal[64] = {0};
    int us_count = (ts % 10000) / 10;
    int ns_count = ts % 10; //unit: 100ns

    ulVal.QuadPart = ts;
    fileTime.dwHighDateTime = ulVal.HighPart;
    fileTime.dwLowDateTime = ulVal.LowPart;

    FileTimeToSystemTime(&fileTime, &sysTime);

    swprintf_s(retVal, L"%d%02d%02d%02d%02d%02d%03d%03d%d%d",
               sysTime.wYear, sysTime.wMonth, sysTime.wDay,
               sysTime.wHour, sysTime.wMinute, sysTime.wSecond,
               sysTime.wMilliseconds, us_count, ns_count, X_10_ns);

    return std::wstring(retVal);
}

uint64_t StringTool::GetNow_FileTime_UTC()
{
    FILETIME fileTime;
    SYSTEMTIME sysTime;
    ULARGE_INTEGER retVal;

    GetSystemTime(&sysTime);
    SystemTimeToFileTime(&sysTime, &fileTime);

    retVal.HighPart = fileTime.dwHighDateTime;
    retVal.LowPart = fileTime.dwLowDateTime;

    return retVal.QuadPart;
}

uint64_t StringTool::FileTime_UTC_to_LTC(uint64_t TsUTC)
{
    ULARGE_INTEGER ulVal;
    FILETIME fileTimeUtc;
    FILETIME fileTimeLtc;

    ulVal.QuadPart = TsUTC;

    fileTimeUtc.dwLowDateTime = ulVal.LowPart;
    fileTimeUtc.dwHighDateTime = ulVal.HighPart;

    FileTimeToLocalFileTime(&fileTimeUtc, &fileTimeLtc);

    ulVal.LowPart = fileTimeLtc.dwLowDateTime;
    ulVal.HighPart = fileTimeLtc.dwHighDateTime;

    return ulVal.QuadPart;
}

uint64_t StringTool::FileTime_LTC_to_UTC(uint64_t TsLTC)
{
    ULARGE_INTEGER ulVal;
    FILETIME fileTimeUtc;
    FILETIME fileTimeLtc;

    ulVal.QuadPart = TsLTC;

    fileTimeLtc.dwLowDateTime = ulVal.LowPart;
    fileTimeLtc.dwHighDateTime = ulVal.HighPart;

    LocalFileTimeToFileTime(&fileTimeLtc, &fileTimeUtc);

    ulVal.LowPart = fileTimeUtc.dwLowDateTime;
    ulVal.HighPart = fileTimeUtc.dwHighDateTime;

    return ulVal.QuadPart;
}

bool StringTool::getTSByFileKeyStr(std::wstring keyFileName, uint64_t &ts, uint32_t &ts_10ns)
{
    auto len = keyFileName.size();
    if (len < 22)
    {
        return false;
    }

    SYSTEMTIME sysTime;

    sysTime.wYear = stoi(keyFileName.substr(0, 4));
    sysTime.wMonth = stoi(keyFileName.substr(4, 2));
    sysTime.wDay = stoi(keyFileName.substr(6, 2));
    sysTime.wHour = stoi(keyFileName.substr(8, 2));
    sysTime.wMinute = stoi(keyFileName.substr(10, 2));
    sysTime.wSecond = stoi(keyFileName.substr(12, 2));
    sysTime.wMilliseconds = stoi(keyFileName.substr(14, 3));

    int rest = stoi(keyFileName.substr(17, 4));
    ts_10ns = stoi(keyFileName.substr(21, 1));

    FILETIME fileTime;
    SystemTimeToFileTime(&sysTime, &fileTime);

    ULARGE_INTEGER ulInt;
    ulInt.LowPart = fileTime.dwLowDateTime;
    ulInt.HighPart = fileTime.dwHighDateTime;

    ulInt.QuadPart += rest;

    ts = ulInt.QuadPart;

    return true;
}

bool StringTool::getTSByFileNameStr(std::string fileName, uint64_t &ts_100ns, uint32_t &ts_10ns)
{
    ts_100ns = 125911584000000000; //若出错，给出时间是2000-01-01 00:00:00:000:000:0
    ts_10ns = 0;

    auto len = fileName.size();
    if (len < 26)
        return false;

    auto array = Stringsplit(fileName, '_');
    if (array.size() < 2)
        return false;

    auto keyFileName = array[0];
    int rest = 0;

    SYSTEMTIME sysTime;

    sysTime.wYear = stoi(keyFileName.substr(0, 4));
    sysTime.wMonth = stoi(keyFileName.substr(4, 2));
    sysTime.wDay = stoi(keyFileName.substr(6, 2));
    sysTime.wHour = stoi(keyFileName.substr(8, 2));
    sysTime.wMinute = stoi(keyFileName.substr(10, 2));
    sysTime.wSecond = stoi(keyFileName.substr(12, 2));
    sysTime.wMilliseconds = stoi(keyFileName.substr(14, 3));

    if (keyFileName.length() > 20)
        rest = stoi(keyFileName.substr(17, 4));

    if (keyFileName.length() > 21)
        ts_10ns = stoi(keyFileName.substr(21, 1));

    FILETIME fileTime;
    SystemTimeToFileTime(&sysTime, &fileTime);

    ULARGE_INTEGER ulInt;
    ulInt.LowPart = fileTime.dwLowDateTime;
    ulInt.HighPart = fileTime.dwHighDateTime;

    ulInt.QuadPart += rest;

    ts_100ns = ulInt.QuadPart;
    return true;
}

std::wstring StringTool::getSrcFileByBurstFile(int channelId, std::wstring burstFile)
{
    std::wstring retVal = L"Error.dat";
    auto var = WStringsplit(burstFile);

    if (var.size() >= 3)
    {
        retVal = var[2] + L"_" + std::to_wstring(channelId) + L".dat";
    }
    else if (var.size() == 2)
    {
        retVal = var[0] + L"_" + std::to_wstring(channelId) + L".dat";
    }

    return retVal;
}

std::vector<uint8_t> StringTool::bytes_to_bits(std::vector<uint8_t> data)
{
    int MSB = 1; //1高位在前 0低位在前
    std::vector<unsigned char> ret;
    int cnt_bit = 0; //位计数，计数到8则跳到下一个字节
    for (auto d = data.begin(); d != data.end(); d++)
    {
        if (cnt_bit == 0) //开辟新字节
        {
            ret.push_back(0);
        }
        int i_bit = cnt_bit;
        if (MSB) //如果高位在前，则需要翻转顺序
        {
            i_bit = 7 - i_bit;
        }
        if (*d != 0) //这一位数据不是0，则对应的位为1
        {
            (*ret.rbegin()) = (*ret.rbegin()) | (0x01 << i_bit); //rbegin是最后一个元素
        }

        cnt_bit = (cnt_bit + 1) % 8; //计数加1，如果满8（一个字节）则跳0
    }
    return ret;
}

uint64_t StringTool::fileTimeToUnixTimeStamp(uint64_t fileTime100Nano)
{
    uint64_t Unix_timestamp = (fileTime100Nano / 10000000) - 11644473600;
    return Unix_timestamp;
}

// 将 FILETIME 转换为 1970 起的秒数和纳秒数
void StringTool::FileTimeToUnixTime(uint64_t &ft_100ns, uint32_t &mFileTS_10ns, int64_t &seconds, int64_t &nanoseconds)
{
    seconds = 0;
    nanoseconds = 0;
    // Windows NT 时间起点（1601-01-01）到 Unix 起点（1970-01-01）的偏移量（100 纳秒为单位）
    const uint64_t EPOCH_DIFF = 116444736000000000ULL; // 11644473600 秒 × 10,000,000

    // 减去偏移量，得到从 1970-01-01 开始的 100 纳秒数
    if (ft_100ns >= EPOCH_DIFF)
    {
        uint64_t unix_100ns = ft_100ns - EPOCH_DIFF;

        // 转换为秒和剩余的纳秒
        seconds = static_cast<int64_t>(unix_100ns / 10000000); // 除以 10,000,000 得到秒
        //nanoseconds = static_cast<int64_t>((unix_100ns % 10000000) * 100); // 剩余部分 × 100 得到纳秒
        nanoseconds += mFileTS_10ns * 10;
    }
    else
    {
        // 文件时间早于 1970 年（罕见）
        seconds = 0;
        nanoseconds = 0;
    }
}

int StringTool::getRandomInt(int min, int max)
{
    // 1. 定义随机数引擎（如默认的随机数引擎）
    std::default_random_engine generator;

    // 2. 定义分布（如整数均匀分布）
    std::uniform_int_distribution<int> distribution(min, max);

    // 3. 生成随机数
    int random_number = distribution(generator);

    return random_number;
}
